package org.huaxi.spring.aop;

import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.huaxi.annotation.DynamicDS;
import org.huaxi.core.DSAnnotationInfo;
import org.huaxi.core.DataSourceNameHolder;
import org.huaxi.internal.DSConfigurationExtractor;
import org.springframework.aop.Pointcut;
import org.springframework.aop.support.AbstractPointcutAdvisor;
import org.springframework.aop.support.annotation.AnnotationMatchingPointcut;

import java.util.Optional;

/**
 * Created by huwei on 2019/5/10.
 */
public class DynamicDSSwitchingAdvisor extends AbstractPointcutAdvisor {

  private final Pointcut pointcut = new AnnotationMatchingPointcut(null, DynamicDS.class);
  private final Advice advice;

  public DynamicDSSwitchingAdvisor(DSConfigurationExtractor dsConfigurationExtractor) {
    this.advice = new SwitchingDSInterceptor(dsConfigurationExtractor);
  }

  @Override
  public Pointcut getPointcut() {
    return this.pointcut;
  }

  @Override
  public Advice getAdvice() {
    return this.advice;
  }

  private static class SwitchingDSInterceptor implements MethodInterceptor {

    private DSConfigurationExtractor dsConfigurationExtractor;

    public SwitchingDSInterceptor(DSConfigurationExtractor dsConfigurationExtractor) {
      this.dsConfigurationExtractor = dsConfigurationExtractor;
    }

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
      Optional<DSAnnotationInfo> dsAnnotationInfo = dsConfigurationExtractor.getDsAnnotationInfo(invocation.getThis(), invocation.getMethod());
      dsAnnotationInfo.ifPresent(dsInfo -> {
        DataSourceNameHolder.set(dsInfo.getName());
      });
      return invocation.proceed();
    }
  }

}
